package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.heima.api.ArticleFeignClient;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.tess4j.Tess4jClient;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 自动审核的逻辑业务类
 */
@Service
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {
    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private GreenTextScan greenTextScan;

    @Autowired
    private GreenImageScan greenImageScan;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private ArticleFeignClient articleFeignClient;

    @Autowired
    private WmUserMapper wmUserMapper;

    @Autowired
    private WmChannelMapper wmChannelMapper;

    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;
    
    @Autowired
    private Tess4jClient tess4jClient;
    /**
     * 自动审核文章
     *
     * @param wmnewsId
     */
    @Override
    @Async//表示当前方法是属于异步线程操作
    public void autoScanWmNews(Integer wmnewsId) {
        //1.根据文章id去查询文章是否存在
        WmNews wmNews = wmNewsMapper.selectById(wmnewsId);
        if(wmNews==null){
            return;
        }
        //如果status=1待审核的时候才可以进行审核操作
        if(wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())){
            //1.5 获取所有的文本和图片
            Map<String, Object> resultMap = chouquImageAndText(wmNews);


            //1.6 应该先自管理敏感词审核，只审核文本
           Boolean sensitiveFlag= handleTextSensitive((String) resultMap.get("content"),wmNews);
            if(!sensitiveFlag){
                return;
            }

            

            //2.文章文本审核
            Boolean textFlag=handleTextScan((String) resultMap.get("content"),wmNews);
            if(!textFlag){
                return;
            }

            //3.文章图片审核
            Boolean imageFlag=handleImageScan((List<String>) resultMap.get("imageList"),wmNews);
            if(!imageFlag){
                return;
            }
            //4.审核通过了，则保存异步调用app端三剑客
            ResponseResult result = saveAppArticle(wmNews);
            if(result.getCode()==200){
                //5.修改wmnews表的状态，并且设置article_id
                wmNews.setArticleId((Long) result.getData());
                updateWmNews(wmNews, (short) 9,"审核通过，文章已发布");
            }
        }
    }

    /**
     * 审核自管理敏感词的操作
     * @param content 文本内容
     * @param wmNews  自媒体实体类
     * @return
     */
    private Boolean handleTextSensitive(String content, WmNews wmNews) {
        Boolean flag=true;
        //1.从数据库表中获取敏感词的集合(只包含敏感词字段)
        List<WmSensitive> wmSensitives = wmSensitiveMapper.selectList(null);//相当于全查
        List<String> sensitiveList = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());
        //2.对敏感词集合进行初始化操作DFA算法
        SensitiveWordUtil.initMap(sensitiveList);

        //3.拿文本内容进行匹配DFA算法，查看是否命中敏感词以及次数
        Map<String, Integer> integerMap = SensitiveWordUtil.matchWords(content);

        //4.如果命中，则表示审核不通过，否则审核通过
        if(integerMap!=null && integerMap.size()>0){
            //修改当前wm_news表的状态
            updateWmNews(wmNews, (short) 2,"文本中包含自管理敏感信息");
            flag=false;
        }
        return  flag;
    }

    /**
     * 同步调用保存app端三剑客操作
     * @param wmNews
     */
    private ResponseResult saveAppArticle(WmNews wmNews) {
        //1.调用feign接口
        ArticleDto dto=new ArticleDto();
        BeanUtils.copyProperties(wmNews,dto);
        //文章布局
        dto.setLayout(wmNews.getType());

        //作者id和名称
        dto.setAuthorId(wmNews.getUserId().longValue());
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
        if(wmUser != null){
            dto.setAuthorName(wmUser.getName());
        }

        //频道名称和id
        dto.setChannelId(wmNews.getChannelId());
        WmChannel wmChannel = wmChannelMapper.selectById(dto.getChannelId());
        if(wmChannel!=null){
            dto.setChannelName(wmChannel.getName());
        }
        dto.setCreatedTime(new Date());
        ResponseResult result = articleFeignClient.save(dto);
        return result;
    }

    /**
     * 审核图片
     * @param imageList
     * @param wmNews
     * @return
     */
    private Boolean handleImageScan(List<String> imageList, WmNews wmNews) {
        Boolean flag=true;

        try {
            List<byte[]> imageByteList=new ArrayList<>();

            //要对imageList做一个去重处理
            imageList=imageList.stream().distinct().collect(Collectors.toList());
            //2.下载图片
            for (String url : imageList) {
                byte[] bytes = fileStorageService.downLoadFile(url);

                //识别Ocr技术
                //ocr图片识别
                ByteArrayInputStream input=new ByteArrayInputStream(bytes);
                BufferedImage bufferImage= ImageIO.read(input);
                //获取图片中的文本内容
                String resultText = tess4jClient.doOCR(bufferImage);
                //文本的审核
                Boolean textSensitiveFlag = handleTextSensitive(resultText, wmNews);
                if(!textSensitiveFlag){
                    return false;
                }

                imageByteList.add(bytes);
            }
            //1.直接调用阿里云图片审核
            Map map = greenImageScan.imageScan(imageByteList);
            if(map!=null && map.size()>0){
                //属于文本违规
                if(map.get("suggestion").equals("block")){
                    //修改status=2
                    updateWmNews(wmNews, (short) 2,"图片中包含敏感信息");
                    flag=false;
                }
                //属于人工审核
                else if(map.get("suggestion").equals("review")){
                    //修改status=3
                    updateWmNews(wmNews, (short) 3,"图片中包含了不确定的信息");
                    flag=false;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            flag=false;
        }
        return flag;
    }

    /**
     * 审核文本
     * @param content
     * @return
     */
    private Boolean handleTextScan(String content,WmNews wmNews) {
        Boolean flag=true;
        //1.直接调用阿里云审核
        try {
            Map map = greenTextScan.greeTextScan(content);
            if(map!=null && map.size()>0){
                //属于文本违规
                if(map.get("suggestion").equals("block")){
                    //修改status=2
                    updateWmNews(wmNews, (short) 2,"文本中包含敏感词汇");
                    flag=false;
                }
                //属于人工审核
                else if(map.get("suggestion").equals("review")){
                    //修改status=3
                    updateWmNews(wmNews, (short) 3,"文本中包含了不确定的词汇");
                    flag=false;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            flag=false;
        }
        return flag;
    }

    /**
     * 修改wmnews表状态
     * @param wmNews
     * @param status
     */
    private void updateWmNews(WmNews wmNews, short status,String message) {
        wmNews.setStatus(status);
        wmNews.setReason(message);
        wmNewsMapper.updateById(wmNews);
    }

    /**
     * 抽取文本和图片
     * @param wmNews
     */
    private Map<String,Object> chouquImageAndText(WmNews wmNews) {
        //声明一个stringbuilder进行封装抽取出来的文本
        StringBuilder sb=new StringBuilder();
        //声明一个list集合进行封装抽取出来的图片
        List<String > imageList=new ArrayList<>();

        //抽取文本
        String title = wmNews.getTitle();
        sb.append(title);//吧当前的标题加入sb中
        //文章内容中包含了文本和图片
        String content = wmNews.getContent();
        List<Map> contentList = JSONArray.parseArray(content, Map.class);
        for (Map map : contentList) {
            //表示文本
            if(map.get("type").equals("text")){
                String text = (String) map.get("value");
                sb.append(text);
            }
            //表示内容中的图片
            if(map.get("type").equals("image")){
                String url = (String) map.get("value");
                imageList.add(url);
            }
        }
        //封面图片也要封装到list中
        String images = wmNews.getImages();//"aa.jpg,bbb.jpg";
        String[] split = images.split(",");
        imageList.addAll(Arrays.asList(split));//["xx.jpg","aa.jpg","bbb.jpg"]

        //返回数据
        Map<String,Object> resultMap=new HashMap<>();
        resultMap.put("content",sb.toString());
        resultMap.put("imageList",imageList);
        return resultMap;
    }
}
